﻿using InfonavaEye.common;
using InfonavaEye.components;
using InfonavaEye.handler;
using InfonavaEye.model;
using InfonavaEye.util;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Media;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
using Color = System.Drawing.Color;
using Pen = System.Drawing.Pen;

namespace InfonavaEye.Forms
{
    public partial class SelectBoxTemplateForm : Form
    {
        public event Action autoStartCloseDelegate;

        public event Action<string> selectTemplateDelegate;

        public string boxModelName;

        public BoxModel boxModel;

        /// <summary>
        /// 正在修改的钉盒模板
        /// </summary>
        public string editBoxModelName;

        /// <summary>
        ///  选择钉盒模板时选中的钉子的字典
        /// </summary>
        private Dictionary<String, Nail> nailListToMap = null;

        public BoxTemplatePreview boxTemplatePreview = new BoxTemplatePreview();

        public SelectBoxTemplateForm(string templateName, List<Nail> oldTemplateNailList)
        {
            InitializeComponent();
            
            this.editBoxModelName = templateName;
            this.boxModelName = templateName;
            boxTemplatePreview.updateNailCountDelegate += BoxTemplatePreview_updateNailCountDelegate;
            if (oldTemplateNailList != null)
            {
                this.nailListToMap = AutoStartParams.nailListToMap(oldTemplateNailList);
            }
        }

        private void PickBoxModelForm_Load(object sender, EventArgs e)
        {
            this.lblTemplateName.Text = this.boxModelName;
            this.selectModeChange();
            
            //选中之前的模板
            Task.Run(async () =>
            {
                await Task.Delay(200);
                loadBoxTemplate();
                
            });
        }

        private void loadBoxTemplate()
        {
            try
            {
                //为每个区域分配一个唯一code:修复模型中的区域code
                if (this.boxModel.boxAreas!=null 
                    && this.boxModel.boxAreas.Count>0 
                    && String.IsNullOrEmpty(this.boxModel.boxAreas[0].code)) {
                    
                    try
                    {
                        this.boxModel.boxAreas.ForEach(p => p.code = Guid.NewGuid().ToString("N"));
                        var boxModelStr = JsonConvert.SerializeObject(this.boxModel);
                        var filePath = util.FileHelper.getBaseDir() + "\\BoxModel\\" + boxModelName + ".json";
                        util.FileHelper.saveFile(boxModelStr, filePath);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("修复模型中的区域code失败，{0} {1}", ex.Message, ex.StackTrace);
                        AutoCloseMessageBox.Show("修复模型中的区域code失败，{0}", ex.Message);
                    }
                }
                //修复boxModel的code
                if (!String.IsNullOrEmpty(this.boxModel.boxCode)) {
                    try
                    {
                        this.boxModel.boxCode =  Guid.NewGuid().ToString("N");
                        var boxModelStr = JsonConvert.SerializeObject(this.boxModel);
                        var filePath = util.FileHelper.getBaseDir() + "\\BoxModel\\" + boxModelName + ".json";
                        util.FileHelper.saveFile(boxModelStr, filePath);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("修复boxModel的code失败，{0} {1}", ex.Message, ex.StackTrace);
                        AutoCloseMessageBox.Show("修复boxModel的code失败，{0}", ex.Message);
                    }
                }
                selectedNailCount = 0;
                boxTemplatePreview.drawAreas(picPreview,boxModel);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        Color bgColor = Color.FromArgb(255, 233, 233, 233);
        private void picPreview_Paint(object sender, PaintEventArgs e)
        {
           /* var g = e.Graphics;
            GraphicsHelper.SetGDIHigh(g);
            GraphicsHelper.FillRoundRectangle(e.ClipRectangle, g, 15, bgColor);*/
        }

        private long prexMoveTimestamp = 0;
        private int prexX = 0;
        private int prexY = 0;
        private Nail preNail = null;
        private bool reDrawing = false;
        Graphics drawG = null;

        /// <summary>
        /// 手指经过每颗钉子 切换钉子状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void picPreview_MouseMove(object sender, MouseEventArgs e)
        {
            //Console.WriteLine("selectMode:" + this.selectMode);
            if (this.selectMode == 0) return;
            if (!(this.mouseLeftKeyDown||mouseRightKeyDown)) return;
            //if (this.selectMode == 0) return;
            if (this.boxModel == null) return;
            //Console.WriteLine("MouseMove,{0},{1}", DateTime.Now, DateTime.Now.Ticks / 100000 - prexMoveTimestamp);

            /* if (prexMoveTimestamp>0 && DateTime.Now.Ticks / 100000 - prexMoveTimestamp < 10) return;
             prexMoveTimestamp = DateTime.Now.Ticks / 100000;*/

            if (reDrawing) { Console.WriteLine("reDrawing return"); return; }
            if (drawingBoxClicked) { Console.WriteLine("drawingBoxClicked 1 return"); return; }
            reDrawing = true;

            try
            {
                if (drawG == null)
                {
                    drawG = picPreview.CreateGraphics();
                    GraphicsHelper.SetGDIHigh(drawG);
                }

                int nailWidth = this.boxTemplatePreview.nailWidth;
                int nailHeight = this.boxTemplatePreview.nailHeight;
                float scaleRate = this.boxTemplatePreview.scaleRate;

                Point dp = new Point(); //定义一个坐标结构
                dp.X = MousePosition.X; //用mousepostion获取鼠标在屏幕中的X轴位置
                dp.Y = MousePosition.Y;//用mousepostion获取鼠标在屏幕中的Y轴位置
                dp = picPreview.PointToClient(dp);  //this 屏幕点的位置转化成工作区坐标
                //Console.WriteLine("dx:{0},dy:{1}", Math.Abs(prexX - dp.X), Math.Abs(prexX - dp.Y));
                if (!(Math.Abs(prexX - dp.X) > (int)(nailWidth * scaleRate) || Math.Abs(prexX - dp.Y) > (int)(nailHeight * scaleRate)))
                {
                    Console.WriteLine("dx dy return");
                    return;
                }
                prexX = dp.X;
                prexY = dp.Y;
                this.boxModel.boxAreas.ForEach((area) =>
                {
                    var startPoint = area.startPoint;

                    for (int i = 0; i < this.boxTemplatePreview.nailList.Count; i++)
                    {
                        var padding = nailWidth * 1 / 4;
                        var nail = this.boxTemplatePreview.nailList[i];
                        var minX = nail.location.X - padding * scaleRate;
                        var maxX = nail.location.X + nail.location.Width + padding * scaleRate;
                        var minY = nail.location.Y - padding * scaleRate;
                        var maxY = nail.location.Y + nail.location.Height+ padding * scaleRate;
                        var point = nail.point;
                        if (dp.X >= minX && dp.X < maxX && dp.Y >= minY && dp.Y < maxY)
                        {
                            if (nail.Equals(preNail) && DateTimeUtil.dateDiffMs(DateTime.Now, nail.updateTime) < 300) return;
                            nail.updateTime = DateTime.Now;
                            preNail = nail;
                            var newStatus = this.selectMode == 1 ? NailStatus.Selected : NailStatus.Normal;
                            if (nail.status!= newStatus) {
                                nail.status = newStatus;
                                updateNailCount(nail.status);
                                this.boxTemplatePreview.drawNail(nail);
                            }
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
               reDrawing = false;
            }
        }

        private int selectedNailCount = 0;
        private void updateNailCount(NailStatus status) {
            selectedNailCount += status == NailStatus.Selected?1:-1;
            lblNailCount.Text = selectedNailCount+"个";

            this.chbLightOnAll.CheckedChanged -= new System.EventHandler(this.chbLightOnAll_CheckedChanged);
            chbLightOnAll.Checked = selectedNailCount == boxTemplatePreview.maxNailCount;
            this.chbLightOnAll.CheckedChanged += new System.EventHandler(this.chbLightOnAll_CheckedChanged);
        }

        private void BoxTemplatePreview_updateNailCountDelegate(NailStatus nailStatus)
        {
            this.updateNailCount(nailStatus);
        }

        private void picPreview_MouseHover(object sender, EventArgs e)
        {

        }

        private void chbLightOnAll_CheckedChanged(object sender, EventArgs e)
        {
            selectAllNail(chbLightOnAll.Checked);
        }

        private void selectAllNail(bool checkAll)
        {
            if (this.boxModel == null || this.boxModel.boxAreas == null) return;
            selectedNailCount = checkAll ? this.boxTemplatePreview.nailList.Count : 0;
            boxTemplatePreview.selectAllNail(checkAll);
            lblNailCount.Text = selectedNailCount + "个";
        }

        private void AutoStartForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.boxTemplatePreview.updateNailCountDelegate -= BoxTemplatePreview_updateNailCountDelegate;
            if (autoStartCloseDelegate != null)
                autoStartCloseDelegate.Invoke();
        }

        private void picPreview_Click(object sender, EventArgs e)
        {
            if (this.boxModel == null) return;
            //Console.WriteLine("MouseMove,{0},{1}", DateTime.Now, DateTime.Now.Ticks / 100000 - prexMoveTimestamp);

            /* if (prexMoveTimestamp>0 && DateTime.Now.Ticks / 100000 - prexMoveTimestamp < 10) return;
             prexMoveTimestamp = DateTime.Now.Ticks / 100000;*/

            if (drawingBoxClicked) { Console.WriteLine("drawingBoxClicked return"); return; }
            drawingBoxClicked = true;

            try
            {
                if (drawG == null)
                {
                    drawG = picPreview.CreateGraphics();
                    GraphicsHelper.SetGDIHigh(drawG);
                }

                int nailWidth = this.boxTemplatePreview.nailWidth;
                int nailHeight = this.boxTemplatePreview.nailHeight;
                float scaleRate = this.boxTemplatePreview.scaleRate;

                Point dp = new Point(); //定义一个坐标结构
                dp.X = MousePosition.X; //用mousepostion获取鼠标在屏幕中的X轴位置
                dp.Y = MousePosition.Y;//用mousepostion获取鼠标在屏幕中的Y轴位置
                dp = picPreview.PointToClient(dp);  //this 屏幕点的位置转化成工作区坐标
                //Console.WriteLine("dx:{0},dy:{1}", Math.Abs(prexX - dp.X), Math.Abs(prexX - dp.Y));
                if (!(Math.Abs(prexX - dp.X) > (int)(nailWidth * scaleRate) || Math.Abs(prexX - dp.Y) > (int)(nailHeight * scaleRate)))
                {
                    Console.WriteLine("dx dy return");
                    return;
                }
                prexX = dp.X;
                prexY = dp.Y;
                var nailFound = false;
                this.boxModel.boxAreas.ForEach((area) =>
                {
                    if (nailFound) return;

                    var startPoint = area.startPoint;
                    for (int i = 0; i < this.boxTemplatePreview.nailList.Count; i++)
                    {
                        var padding = nailWidth * 1/4;
                        var nail = this.boxTemplatePreview.nailList[i];
                        var minX = nail.location.X - padding * scaleRate;
                        var maxX = nail.location.X + nail.location.Width + padding * scaleRate;
                        var minY = nail.location.Y - padding * scaleRate;
                        var maxY = nail.location.Y + nail.location.Height + padding * scaleRate;
                        var point = nail.point;
                        if (dp.X >= minX && dp.X < maxX && dp.Y >= minY && dp.Y < maxY)
                        {
                            nailFound = true;
                            nail.status = nail.status == NailStatus.Normal? NailStatus.Selected : NailStatus.Normal;
                            updateNailCount(nail.status);
                            this.boxTemplatePreview.drawNail(nail);
                            break;
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Task.Factory.StartNew(async () =>
                {
                    await Task.Delay(100);
                    drawingBoxClicked = false;
                });
            }
        }

        bool drawingBoxClicked = false;
        private void picPreview_DoubleClick(object sender, EventArgs e)
        {
            
        }

        /// <summary>
        /// 选中模式：0 没有动作，1.选中，2.反选
        /// </summary>
        int selectMode = 1;
        private void btnSelect_Click(object sender, EventArgs e)
        {
            if (this.selectMode == 1)
            {
                this.selectMode = 2;
            }
            else {
                this.selectMode = 1;
            }
            this.selectModeChange();
        }

        private void btnUnSelect_Click(object sender, EventArgs e)
        {
            if (this.selectMode == 2)
            {
                this.selectMode = 1;
            }
            else
            {
                this.selectMode = 2;
            }
            this.selectModeChange();
        }

        private void selectModeChange() {
            if (this.selectMode == 0)
            {
                this.btnSelect.ForeColor = Color.Gray;
                this.btnSelect.BackColor= Color.White;
                this.btnUnSelect.ForeColor = Color.Gray;
                this.btnUnSelect.BackColor = Color.White;
            }
            else if (this.selectMode == 1) {
                this.btnSelect.ForeColor = Color.Black;
                this.btnSelect.BackColor = Color.LightBlue;
                this.btnUnSelect.ForeColor = Color.Gray;
                this.btnUnSelect.BackColor = Color.White;
            } else if (this.selectMode == 2) {
                this.btnSelect.ForeColor = Color.Gray;
                this.btnSelect.BackColor = Color.White;
                this.btnUnSelect.ForeColor = Color.Black;
                this.btnUnSelect.BackColor = Color.LightBlue;
            }
        }

        private void btnNoneSelect_Click(object sender, EventArgs e)
        {
            this.selectMode = 0;
            this.selectModeChange();
        }

        bool mouseLeftKeyDown = false;
        bool mouseRightKeyDown = false;

        private void picPreview_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left) {
                mouseLeftKeyDown = true;
                mouseRightKeyDown = true;
            }
        }

        private void picPreview_MouseUp(object sender, MouseEventArgs e)
        {
            mouseLeftKeyDown = false;
            mouseRightKeyDown = false;
        }

        /// <summary>
        /// 校准原点的位置（x,y）
        /// </summary>
        public XYZ[] fixZeroLocation;

        private void btnSure_Click(object sender, EventArgs e)
        {
            if (this.boxTemplatePreview.nailList == null || !this.boxTemplatePreview.nailList.Any(p => p.status == NailStatus.Selected))
            {
                MessageBox.Show("请选择要识别的钉子");
                return;
            }

            OriginAdjustForm step2 = new OriginAdjustForm();
            step2.boxModel = this.boxModel;
            var result = step2.ShowDialog();
            if (result == DialogResult.OK)
            {
                this.fixZeroLocation = step2.fixZeroLocation;
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

